// Copyright (C) 1953-2022 NUDT
// Verilog module name - ptp_process
// Version: V4.1.0.20221205
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         receive ptp packet
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module ptp_process#(parameter ptp_rx_offset = 16'd192)
(
    i_clk  ,
    i_rst_n,

    i_slave_port  ,
    
    //iv_local_count,
    
    iv_data  ,
    i_data_wr,
    
    ov_data       ,
    o_data_wr     ,
    ov_eth_type        ,
    ov_ptp_messagetype ,
    //ov_local_count_rx  ,
    o_diagest_wr       ,    
    
    o_osm_req_rx_pulse       ,
    o_osm_resp_rx_pulse      ,
    o_osm_sync_rx_pulse
    //o_sync_pulse_portrx
);
// I/O
// clk & rst
input                   i_clk  ;
input                   i_rst_n;
//input
input                   i_slave_port  ;
   
//input       [39:0]      iv_local_count;

input       [8:0]       iv_data  ;
input                   i_data_wr;
//output
output  reg [8:0]       ov_data             ;
output  reg             o_data_wr           ;
output  reg [15:0]      ov_eth_type         ;
output  reg [3:0]       ov_ptp_messagetype  ;
//output  reg [39:0]      ov_local_count_rx   ;
output  reg             o_diagest_wr        ;

output  reg             o_osm_req_rx_pulse        ;
output  reg             o_osm_resp_rx_pulse       ;
output  reg             o_osm_sync_rx_pulse       ;
//***************************************************
//   add valid of data and delay 14 cycles
//***************************************************
//internal wire
reg         [125:0]     rv_data;
reg         [10:0]      rv_byte_cnt; 
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n) begin
        rv_data  <= 126'b0;
        rv_byte_cnt  <= 11'b0;
    end
    else begin
        if(i_data_wr)begin
            rv_byte_cnt <= rv_byte_cnt +1'b1;
            rv_data     <= {rv_data[116:0],iv_data};
        end
        else begin
            rv_data     <= {rv_data[116:0],9'b0};  
            rv_byte_cnt <= 11'b0;           
        end
    end
end  
//***************************************************
//               ptp distinguish
//***************************************************
(*MARK_DEBUG="true"*)reg         [7:0]      rv_response_cnt;
(*MARK_DEBUG="true"*)reg         [7:0]      rv_response_follow_up_cnt;
(*MARK_DEBUG="true"*)reg         [15:0]     rv_pkt_cnt_macrx;
    
reg         [3:0]       rv_ppr_state;
localparam  IDLE_S             = 4'd0,
            TRAN_PKT_S         = 4'd1,
            DISC_PKT_S         = 4'd2;            
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        ov_data             <= 9'b0;
        o_data_wr           <= 1'b0;
        
        ov_eth_type         <= 16'b0;
        ov_ptp_messagetype  <= 4'b0;
        o_osm_req_rx_pulse  <= 1'b0;
		o_osm_resp_rx_pulse <= 1'b0;
		o_osm_sync_rx_pulse <= 1'b0;
		        
        //o_sync_pulse_portrx <= 1'b0;
 
        rv_ppr_state        <= IDLE_S;
        
        rv_response_cnt           <= 8'b0;
        rv_response_follow_up_cnt <= 8'b0;
		rv_pkt_cnt_macrx          <= 16'b0;
    end
    else begin
        case(rv_ppr_state)
            IDLE_S:begin
                if(rv_byte_cnt == 11'd14)begin                  
                    ov_eth_type         <= {rv_data[16:9],rv_data[7:0]};
                    ov_ptp_messagetype  <= iv_data[3:0];
                    if({rv_data[16:9],rv_data[7:0]} == 16'h88f7)begin//eth type.
                        if(iv_data[3:0] == 4'h0)begin//sync    
                            o_osm_req_rx_pulse          <= 1'b0;
                            o_osm_resp_rx_pulse         <= 1'b0;
                            if(i_slave_port)begin//slave port.
                                o_diagest_wr                <= 1'b1;                                
                                o_data_wr                   <= 1'b1;
                                ov_data                     <= rv_data[125:117]; 
								o_osm_sync_rx_pulse 		<= 1'b1;                             
                                rv_ppr_state                <= TRAN_PKT_S; 
                            end
                            else begin
                                o_diagest_wr                <= 1'b0;
                                o_data_wr                   <= 1'b0;
                                ov_data                     <= 9'b0; 
								o_osm_sync_rx_pulse 		<= 1'b0;
                                rv_ppr_state                <= DISC_PKT_S;    
                            end   
                        end
                        else if(iv_data[3:0] == 4'h2)begin//pdelay_req                          
                            o_diagest_wr                <= 1'b1;
                            o_data_wr                   <= 1'b1;
                            ov_data                     <= rv_data[125:117];  
                            rv_ppr_state                <= TRAN_PKT_S; 
                                
                            o_osm_req_rx_pulse          <= 1'b1;
                            o_osm_resp_rx_pulse         <= 1'b0; 
							o_osm_sync_rx_pulse 		<= 1'b0;
                        end
                        else if(iv_data[3:0] == 4'h3)begin//pdelay_resp 
                            o_diagest_wr                <= 1'b1;
                            o_data_wr                   <= 1'b1;
                            ov_data                     <= rv_data[125:117];  
                            rv_ppr_state                <= TRAN_PKT_S; 
                            
                            o_osm_req_rx_pulse          <= 1'b0;
                            o_osm_resp_rx_pulse         <= 1'b1;
                            o_osm_sync_rx_pulse 		<= 1'b0;
                            rv_response_cnt           <= rv_response_cnt + 1'b1;                                                    
                        end
						else if(iv_data[3:0] == 4'h8)begin//follow_up    
                            o_osm_req_rx_pulse          <= 1'b0;
                            o_osm_resp_rx_pulse         <= 1'b0;
							o_osm_sync_rx_pulse 		<= 1'b0;
                            if(i_slave_port)begin//slave port.
                                o_diagest_wr                <= 1'b1;                                
                                o_data_wr                   <= 1'b1;
                                ov_data                     <= rv_data[125:117];                             
                                rv_ppr_state                <= TRAN_PKT_S; 
                            end
                            else begin
                                o_diagest_wr                <= 1'b0;
                                o_data_wr                   <= 1'b0;
                                ov_data                     <= 9'b0; 
                                rv_ppr_state                <= DISC_PKT_S;    
                            end   
                        end                                               
                        else begin
                            o_diagest_wr                <= 1'b1;
                            o_data_wr                   <= 1'b1;
                            ov_data                     <= rv_data[125:117];  
                            rv_ppr_state                <= TRAN_PKT_S;                            
                            o_osm_req_rx_pulse          <= 1'b0;
                            o_osm_resp_rx_pulse         <= 1'b0;
							o_osm_sync_rx_pulse 		<= 1'b0;
                            if(iv_data[3:0] == 4'hA)begin//pdelay_resp_follow_up
                                rv_response_follow_up_cnt <= rv_response_follow_up_cnt + 1'b1;
                            end
                            else begin
                                rv_response_follow_up_cnt <= rv_response_follow_up_cnt;
                            end                             
                        end
					end 
                    else begin
                        o_diagest_wr                <= 1'b1;
                        o_data_wr                   <= 1'b1;
                        ov_data                     <= rv_data[125:117];  
                        rv_ppr_state                <= TRAN_PKT_S; 
                        
                        o_osm_req_rx_pulse          <= 1'b0;
                        o_osm_resp_rx_pulse         <= 1'b0;
						o_osm_sync_rx_pulse 		<= 1'b0;
                        //o_sync_pulse_portrx         <= 1'b0;                        
					end
                end
				else begin
                    ov_data             <= 9'b0;
                    o_data_wr           <= 1'b0;
                    o_diagest_wr        <= 1'b0;
                    ov_eth_type         <= 16'b0;
                    ov_ptp_messagetype  <= 4'b0;                    
                    o_osm_req_rx_pulse  <= 1'b0;
                    o_osm_resp_rx_pulse <= 1'b0;
					o_osm_sync_rx_pulse <= 1'b0;                    
                    //o_sync_pulse_portrx <= 1'b0;             
                    rv_ppr_state        <= IDLE_S;             
                end
            end
			
            TRAN_PKT_S:begin   
                o_osm_req_rx_pulse  <= 1'b0;
                o_osm_resp_rx_pulse <= 1'b0;
				o_osm_sync_rx_pulse <= 1'b0;
                //o_sync_pulse_portrx <= 1'b0;
                o_data_wr           <= 1'b1;
                ov_data             <= rv_data[125:117];                  
                o_diagest_wr        <= 1'b0;
                if(rv_data[125]) begin   //transmit data.
                    rv_pkt_cnt_macrx <= rv_pkt_cnt_macrx + 1'b1;
					rv_ppr_state     <= IDLE_S;                    
                end
                else begin
                    rv_ppr_state    <= TRAN_PKT_S;
                end
            end 
            DISC_PKT_S:begin   
                o_osm_req_rx_pulse  <= 1'b0;
                o_osm_resp_rx_pulse <= 1'b0;
				o_osm_sync_rx_pulse <= 1'b0;
                //o_sync_pulse_portrx <= 1'b0;
                o_data_wr           <= 1'b0;
                ov_data             <= 9'b0;                  
                o_diagest_wr        <= 1'b0;
                if(rv_data[125]) begin   //transmit data.
                    rv_ppr_state    <= IDLE_S;
                end
                else begin
                    rv_ppr_state    <= DISC_PKT_S;                    
                end
            end            
            default:begin
                ov_data             <= 9'b0;
                o_data_wr           <= 1'b0;
                //ov_local_count_rx   <= 40'b0;
                ov_eth_type         <= 16'b0;
                ov_ptp_messagetype  <= 4'b0;
                o_diagest_wr        <= 1'b0;
                
                o_osm_req_rx_pulse  <= 1'b0;
                o_osm_resp_rx_pulse <= 1'b0;
				o_osm_sync_rx_pulse <= 1'b0;
                //o_sync_pulse_portrx <= 1'b0;
         
                rv_ppr_state        <= IDLE_S;     
            end
        endcase
    end
end   
endmodule
